<template>
  <el-dialog :title="title" :close-on-click-modal="false" :show-close="false" visible :close-on-press-escape="false"
    destroy-on-close width="1000px">
    <div class="infoMessage">
      <i class="el-icon-warning-outline"></i> 表单规则条件互斥时按照“隐藏>显示>（表单字段隐藏）>只读>必填”优先级执行</div>
    <el-form :inline="true" class="basicForm" size="small" ref="basic" :model="basic">
      <el-form-item label="规则名称" prop="name"
        :rules="[{required:true,message:'请输入规则名称',trigger:'blur'},{pattern:/^[\s\S]*.*[^\s][\s\S]*$/,message:'名称不能为空，且不能仅包含空格'}]"
        style="margin-right:0px;">
        <el-input size="small" style="width:390px;" v-model="basic.name"></el-input>
      </el-form-item>
      <el-form-item prop="order" :rules="[{required:true,message:'请输入批次',trigger:'blur'}]" style="margin-right:0px;">
        <template slot="label">批次 <el-tooltip class="item" effect="dark"
            content="批次数字越小，则表单规则的优先级越高，当满足某一批次的规则时，当前批次所有规则都可以进行筛选，当筛选的规则也满足时，则回显触发对应配置。" placement="top">
            <i class="el-icon-warning-outline"></i>
          </el-tooltip>
        </template>
        <el-input-number size="small" style="width:390px;" :min="0" :max="1000" v-model="basic.order"></el-input-number>
      </el-form-item>
    </el-form>
    <div class="wrapper">
      <div class="titleText">规则设置</div>
      <div style="position:relative;top:-10px;">
        <el-button type="primary" icon="el-icon-plus" size="small" style="border-radius:2px;margin-right:10px" @click="addRule">添加规则
        </el-button>
        <el-button type="success" icon="el-icon-folder" size="small"
          style="border-radius:2px;margin-left:0px;margin-bottom:10px;" @click="addGroup"
          :disabled="ruleGroup[0].rules.length===0">添加组</el-button>
        <template v-for="(item,index) in ruleGroup">
          <div class="groupBorder2" v-if="index>0">
            <el-select style="width:100%;" size="small" v-model="methods[index-1]">
              <el-option label="或" value="or"></el-option>
              <el-option label="且" value="and"></el-option>
            </el-select>
          </div>
          <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;"
            @click="()=>{currentGroup=index}">
            <div v-if="item.rules.length>0"
              :style="{border:index===currentGroup?'1px solid #1890ff':'1px solid #DCDFE6',width:'85%'}">
              <template v-for="(rule,ind) in item.rules">
                <div style="display:flex;align-items:center;flex-direction:row;">
                  <div class="ruleRow" style="width:85%;margin-left:10px;">
                   <div class="ruleRowList">
                      <el-select style="width:32%;margin-right:10px;" size="small" v-model="rule.fieldName"
                        @change="(val)=>{changeCompare(val,ind)}" @focus="()=>{currentGroup=index}">
                        <el-option v-for="(field) in fieldNames" :key="field.value" :label="field.label" :value="field.value"></el-option>
                      </el-select>
                      <template>
                        <el-select style="width:32%;margin-right:10px;" size="small"
                          v-if="getType(rule.fieldName) === 'number'" v-model="rule.compare"
                          @focus="()=>{currentGroup=index}">
                          <el-option v-for="(ruleItem) in numberSelection" :key="ruleItem.value" :label="ruleItem.label"
                            :value="ruleItem.value">
                          </el-option>
                        </el-select>
                        <el-select style="width:32%;margin-right:10px;" size="small" v-else v-model="rule.compare"
                          @focus="()=>{currentGroup=index}">
                          <el-option v-for="(ruleItem) in textSelection" :key="ruleItem.value" :label="ruleItem.label"
                            :value="ruleItem.value">
                          </el-option>
                        </el-select>
                      </template>
                      <template>
                        <el-select v-if="['switch', 'select', 'radio', 'checkbox'].includes(getTag(rule.fieldName))"
                          v-model="rule.content" style="width:32%;">
                          <el-option v-for="opt in getOption(rule.fieldName)" :key="opt.value" :label="opt.label" :value="opt.value">
                          </el-option>
                        </el-select>
                        <el-cascader v-else-if="['cascader','tree-table'].includes(getTag(rule.fieldName))"
                          style="width:32%;" v-model="rule.content" :options="getOption(rule.fieldName)"
                          :props="{ checkStrictly: true }">
                        </el-cascader>
                        <el-input-number v-else-if="['number','slider','rate', 'numbers'].includes(getTag(rule.fieldName))"
                          style="width:32%;" size="small" v-model="rule.content"></el-input-number>
                        <el-time-picker v-else-if="getTag(rule.fieldName) === 'time'" style="width:32%;" size="small"
                          v-model="rule.content" value-format="HH:mm:ss"></el-time-picker>
                        <el-date-picker v-else-if="getTag(rule.fieldName) === 'date'" style="width:32%;" size="small"
                          v-model="rule.content" :type="getOption(rule.fieldName)[0]"
                          :format="getOption(rule.fieldName)[1]" :value-format="getOption(rule.fieldName)[1]">
                        </el-date-picker>
                        <el-input v-else style="width:32%;" size="small" v-model="rule.content">
                        </el-input>
                      </template>
                    </div>
                    <el-button icon="el-icon-delete" size="small"  style="margin-left:10px;height:30px;margin-top: 10px" class="delBTN"
                      @click="delRule(ind,index)" circle></el-button>
                  </div>
                  <div class="groupBorder" v-if="ind>0">
                    <el-select style="width:100%;" size="small" v-model="item.method[ind-1]">
                      <el-option label="或" value="or"></el-option>
                      <el-option label="且" value="and"></el-option>
                    </el-select>
                  </div>
                </div>
              </template>
            </div>
            <el-button v-if="item.rules.length>0" icon="el-icon-delete" size="small" class="delBTN"
              @click="delRuleGroup(index)" circle>
            </el-button>
          </div>

        </template>
        <div class="ruleInfo">
          <div>满足规则后，触发以下配置:</div>
          <div style="display:flex;margin-top:10px;">
            <div class="leftTitle">字段配置</div>
            <div style="width:90%;">
              <div style="margin-bottom:10px;">
                <el-select size="small" style="width:11%;" v-model="fieldConfig.onlyHidden" :disabled="ruleGroup[0].rules.length  === 0">
                  <el-option v-for="(item) in displayHiddenList" :key="item.value" :label="item.label" :value="item.value"></el-option>
                </el-select>
                <span style="margin:0px 10px;">隐藏</span>
                <el-select size="small" style="width:78%;" v-model="fieldConfig.hide" multiple clearable :disabled="ruleGroup[0].rules.length  === 0">
                  <el-option v-for="(item) in fieldNames" :key="item.value" :label="item.label" :value="item.value"></el-option>
                </el-select>
                <span style="margin-left:10px;">字段</span>
              </div>
              <div style="margin-bottom:10px;">
                <el-select size="small" style="width:11%;" v-model="fieldConfig.onlyDisplay" :disabled="ruleGroup[0].rules.length  === 0">
                  <el-option v-for="(item) in displayHiddenList" :key="item.value" :label="item.label" :value="item.value"></el-option>
                </el-select>
                <span style="margin:0px 10px;">显示</span>
                <el-select size="small" style="width:78%;" v-model="fieldConfig.show" multiple clearable :disabled="ruleGroup[0].rules.length  === 0">
                  <el-option v-for="(item) in fieldNames" :key="item.value" :label="item.label" :value="item.value"
                    :disabled="fieldConfig.hide.includes(item.value)"></el-option>
                </el-select>
                <span style="margin-left:10px;">字段</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div slot="footer" class="dialog-footer">
      <el-button @click="close">取 消</el-button>
      <el-button @click="clear">清空</el-button>
      <el-button type="primary" @click="submit">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script>
  const intTypes = ['el-input-number', 'el-slider', 'el-rate'];  //数字类型组件
  const specialTypes = ['switch', 'cascader', 'select', 'radio', 'checkbox', 'tree-table']; //特殊组件，需处理后在table中展示
  import {
    regionData
  } from "element-china-area-data";
  import {
    getColumnData,
    getDictData
  } from '@/api/custom/formDesigner'
  import {
    getAllListData
  } from "@/api/custom/formPoster";
  export default {
    props: ['fields', 'ruleConfig'],
    data() {
      return {
        displayHiddenList: [
            {
                value: 1,
                label: '就'
            },
            {
                value: 0,
                label: '只'
            }
        ],
        title: '新增表单规则', //弹窗标题
        currentIndex: '', //当前规则索引
        //文本类型操作选项
        textSelection: [{
            label: '等于',
            value: 'seq'
          },
          {
            label: '不等于',
            value: 'sne'
          },
          {
            label: '内容包含',
            value: 'sge'
          },
          {
            label: '内容不包含',
            value: 'sle'
          }
        ],
        //数字类型操作选项
        numberSelection: [{
            label: '等于',
            value: 'eq'
          },
          {
            label: '不等于',
            value: 'ne'
          },
          {
            label: '小于',
            value: 'lt'
          },
          {
            label: '小于等于',
            value: 'le'
          },
          {
            label: '大于',
            value: 'gt'
          },
          {
            label: '大于等于',
            value: 'ge'
          }
        ],
        fieldNames: [], //表单字段
        basic: {
          name: '', //规则名称
          order: '' //批次
        },
        ruleGroup: [{
          rules: [], //规则
          method: [] //且、或
        }],
        fieldConfig: {
            onlyDisplay: 0,  // 默认 只 显示
            onlyHidden: 0, // 默认 只 隐藏
            hide: [], //隐藏字段
            show: [] //显示字段
        },
        methods: [], //且、或
        currentGroup: 0 //当前规则组
      } 
    },
    mounted() {
      this.getTagIcons(this.fields) //获取各字段
    },
    methods: {
      //初始化表单规则
      init(data, index) {
        if (index !== undefined) { //编辑，变量赋值
          this.title = '编辑表单规则'
          this.basic = {
            ...data.basic
          }
          this.ruleGroup = [...data.formrule]
          this.methods = [...data.method]
          this.fieldConfig.hide = [...data.hide]
          this.fieldConfig.show = [...data.show]
          this.fieldConfig.onlyDisplay = data.onlyDisplay
          this.fieldConfig.onlyHidden = data.onlyHidden
          this.currentIndex = index
          this.currentGroup = 0
        } else { //新增
          this.title = '新增表单规则'
          this.currentIndex = ''
          this.clear()
          this.basic.order = this.ruleConfig.length
        }
      },
      //取消
      close() {
        this.$emit('close')
      },
      //清空、重置各变量
      clear() {
        this.basic.name = ''
        this.basic.order = ''
        this.fieldConfig.hide= []
        this.fieldConfig.show = []
        this.fieldConfig.onlyDisplay = ''
        this.fieldConfig.onlyHidden = ''
        this.ruleGroup = [{
          rules: [],
          method: []
        }]
        this.methods = []
        this.currentGroup = 0
      },
      //确定
      submit() {
        const existIdx = this.ruleConfig.findIndex(item => {
            return item.basic.order === this.basic.order
        })
        if (existIdx !== -1 && this.title === '新增表单规则') {
            this.$message.closeAll()
            this.$message.warning('已存在该批次，请重新填写')
            return 
        }
        this.$refs.basic.validate((valid) => {
          if (valid) {
            if (this.ruleGroup[0]?.rules.length === 0) {
              this.$message.warning('请添加规则或添加组')
            } else {
              if (this.currentIndex === '') {
                this.$emit('commit', this.basic, this.ruleGroup, this.methods, this.fieldConfig) //新增
              } else {
                this.$emit('update', this.basic, this.ruleGroup, this.methods, this.fieldConfig, this.currentIndex) //修改
              }
              this.close()
            }
            return true
          } else {
            return false
          }
        })
      },
      //添加规则
      addRule() {
        this.ruleGroup[this.currentGroup].rules.push({
          fieldName: '', //字段名
          compare: 'seq', //操作
          content: '', //内容
        })
        this.ruleGroup[this.currentGroup].method.push('or')
      },
      //添加组
      addGroup() {
        this.ruleGroup.push({
          rules: [{
            fieldName: '',
            compare: 'seq',
            content: '',
          }],
          method: []
        })
        this.methods.push('or')
      },
      //删除规则或组
      delRule(ind, index) {
        this.ruleGroup[index]?.rules.splice(ind, 1)
        if(this.ruleGroup[0]?.rules == 0 ){ //没有规则的时候 清空字段配置
            this.fieldConfig.onlyHidden = ''
            this.fieldConfig.hide = ''
            this.fieldConfig.onlyDisplay = ''
            this.fieldConfig.show = ''
        }
        if (this.ruleGroup[index].method.length === 0) {
          setTimeout(() => {
            this.delRuleGroup(index)
          }, 10)
        }
        this.ruleGroup[index].method.splice(ind >= this.ruleGroup[index].method.length ? ind - 1 : ind, 1)
      },
      //删除规则组
      delRuleGroup(index) {
        this.ruleGroup.splice(index, 1)
        if(this.ruleGroup.length === 0){ //没有规则的时候 清空字段配置
            this.ruleGroup = [{
                rules: [],
                method: []
            }]
            this.fieldConfig.onlyHidden = ''
            this.fieldConfig.hide = ''
            this.fieldConfig.onlyDisplay = ''
            this.fieldConfig.show = ''
        }
        this.methods.splice(index >= this.methods.length ? index - 1 : index, 1)
      },
      //更改字段选择
      changeCompare(val, index) {
        let type = this.getType(val)
        this.ruleGroup[this.currentGroup].rules[index].compare = type === 'number' ? 'eq' : 'seq'
        this.ruleGroup[this.currentGroup].rules[index].content = ''
      },
      //获取字段规则type：数字'number'、文本'text'
      getType(type) {
        if (!type) {
          return ''
        }
        let field = this.fieldNames.filter((item) => {
          return item.value === type
        })
        return field[0]?.type
      },
      //获取字段tagIcon图标
      getTag(type) {
        if (!type) {
          return ''
        }
        let field = this.fieldNames.filter((item) => {
          return item.value === type
        })
        return field[0]?.tag
      },
      //获取字段Option
      getOption(type) {
        let field = this.fieldNames.filter((item) => {
          return item.value === type
        })
        return field[0]?.option
      },
      //获取所有字段
      async getTagIcons(data) {
        if (data.length === 0) return
        let comps = data.filter((item) => {
          return item.__config__.tag !== 'TitleLine' //过滤标题和分割线
        })
        for (let i = 0; i < comps.length; i++) {
          let item = comps[i]
          if (item.__config__.tag === 'el-card' || item.__config__.tag === 'el-tabs' || item.__config__.tag === 'Steps' || item.__config__.tag ===
            'el-collapse') {
            //布局组件，遍历内部子组件
            let tem = item.__config__.children.map((c) => {
              this.getTagIcons(c.__config__.children)
            })
          } else {
            let tag = item.__config__.tagIcon
            let type = 'number'
            if (!intTypes.includes(item.__config__.tag)) {
              type = 'text'
            }
            let options = []
            if (tag === 'switch') {
              options = [{
                label: '是',
                value: item['active-value']
              }, {
                label: '否',
                value: item['inactive-value']
              }]
              this.fieldNames.push({
                value: item.__vModel__,
                type: type,
                label: item.__config__.label,
                tag: item.__config__.tagIcon,
                option: [...options]
              })
            } else if (['select', 'radio', 'checkbox'].includes(tag)) {
              if (item.dataType === 'static') { //静态数据
                options = item.options
                this.fieldNames.push({
                  value: item.__vModel__,
                  type: type,
                  label: item.__config__.label,
                  tag: item.__config__.tagIcon,
                  option: [...options]
                })
              } else if (item.dataType === 'dictionary' && item.dictName !== '') { //字典数据
                let res = await getDictData({
                  dictType: item.dictName
                })
                if (res.code === 0) {
                  res.data.forEach((item) => {
                    options.push({
                      label: item.label,
                      value: item.label
                    })
                  })
                }
                this.fieldNames.push({
                  value: item.__vModel__,
                  type: type,
                  label: item.__config__.label,
                  tag: item.__config__.tagIcon,
                  option: [...options]
                })
              } else if (item.dataType === 'datasource' && item.tableName !== '' && item.fieldName !== '') { //动态数据
                let res = await getColumnData({
                  tableName: item.tableName,
                  column: item.fieldName,
                })
                if (res.code === 0) {
                  res.data.forEach((item) => {
                    options.push({
                      label: item,
                      value: item
                    })
                  })
                }
                this.fieldNames.push({
                  value: item.__vModel__,
                  type: type,
                  label: item.__config__.label,
                  tag: item.__config__.tagIcon,
                  option: [...options]
                })
              }
            } else if (tag === 'cascader' || tag === 'tree-table') {
              if (item.dataType === 'dynamic') { //动态数据
                await this.getDynamicOptions(item.fields, item.formName).then(res => {
                  options = res
                })
                this.fieldNames.push({
                  value: item.__vModel__,
                  type: type,
                  label: item.__config__.label,
                  tag: item.__config__.tagIcon,
                  option: [...options]
                })
              } else if (item.dataType === 'static') { //静态数据
                options = item.options
                this.fieldNames.push({
                  value: item.__vModel__,
                  type: type,
                  label: item.__config__.label,
                  tag: item.__config__.tagIcon,
                  option: [...options]
                })
              } else if (item.dataType === 'region') { //行政区域
                this.fieldNames.push({
                  value: item.__vModel__,
                  type: type,
                  label: item.__config__.label,
                  tag: item.__config__.tagIcon,
                  option: regionData
                })
              }
            } else if (tag === 'date') {
              this.fieldNames.push({
                value: item.__vModel__,
                type: type,
                label: item.__config__.label,
                tag: item.__config__.tagIcon,
                option: [item.type, item['value-format']]
              })
            } else {
              this.fieldNames.push({
                value: item.__vModel__,
                type: type,
                label: item.__config__.label,
                tag: item.__config__.tagIcon
              })
            }
          }
        }
      },
      //获取动态option
      async getDynamicOptions(fields, formName) {
        let params = {
          tableName: formName,
          dataType: '2'
        }
        let res = await getAllListData(params)
        let options = []
        if (res.code === 0) {
          let tableData = res.data
          if (fields.length > 0) {
            for (let i = 0; i < fields[0].datas.length; i++) {
              let opt = fields[0].datas[i]
              let values = await getColumnData({
                tableName: formName,
                column: opt.fieldName,
              })
              values.data.map((item) => {
                let node = {
                  label: item,
                  value: item
                }
                let child = this.getChildren(opt.fieldName, item, 1, fields, tableData)
                if (child.length > 0) {
                  node.children = child
                }
                options.push(node)
              })
            }
          }
        }
        return options
      },
      //获取子级
      getChildren(name, data, index, fields, tableData) {
        let option = []
        if (index >= fields.length) {
          return option
        } else {
          fields[index].datas.map((item) => {
            if (item.parent === name) {
              [...new Set(tableData.filter((field) => {
                return field[name] === data
              }).map((field) => {
                return field[item.fieldName]
              }))].map((field) => {
                let node = {
                  label: field,
                  value: field
                }
                let child = this.getChildren(item.fieldName, field, index + 1, fields, tableData)
                if (child.length > 0) {
                  node.children = child
                }
                option.push(node)
              })
            }
          })
          return option
        }
      }
    }
  }

</script>
<style lang="scss" scoped>
  .infoMessage {
    color: #E8940C;
    padding: 20px 10px 10px;
    margin-bottom: 10px;
  }

  .basicForm {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
  }

  .wrapper {
    border: 1px solid #DCDFE6;
    min-height: 100px;
    padding: 10px;

    .titleText {
      position: relative;
      background: white;
      top: -22px;
      padding-left: 10px;
      width: 95px;
      font-size: 18px;
    }

    .ruleInfo {
      background: #FCFCDB;
      padding: 10px;

      .infoText {
        color: #E8940C;
        padding: 10px;
        margin-bottom: 10px;
        display: flex;
        align-items: center;
      }

      .leftTitle {
        padding-right: 10px;
        margin-right: 10px;
        color: #1890ff;
        font-size: 16px;
      }
    }
  }

  .ruleRow {
    display: flex;
    // padding: 8px;
    margin: 10px 0px;
  }
  .ruleRowList{
    background: #EEF7FF;
    width: 100%;
    padding: 8px;
  }
  .groupBorder {
    width: 6.5%;
    right: 18.5%;
    margin-top: -7%;
    position: absolute;
  }

  .groupBorder::before {
    position: absolute;
    top: -15px;
    left: -18px;
    width: 50px;
    height: 15px;
    border-right: 1px solid #DCDFE6;
    border-top: 1px solid #DCDFE6;
    content: '';
  }

  .groupBorder::after {
    position: absolute;
    top: 31px;
    left: -18px;
    width: 50px;
    height: 15px;
    border-right: 1px solid #DCDFE6;
    border-bottom: 1px solid #DCDFE6;
    content: '';
  }

  .groupBorder2 {
    width: 6.5%;
    right: 6.5%;
    margin-top: -2%;
    position: absolute;
  }

  .groupBorder2::before {
    position: absolute;
    top: -15px;
    left: -18px;
    width: 70px;
    height: 15px;
    border-right: 1px solid #DCDFE6;
    border-top: 1px solid #DCDFE6;
    content: '';
  }

  .groupBorder2::after {
    position: absolute;
    top: 31px;
    left: -18px;
    width: 70px;
    height: 15px;
    border-right: 1px solid #DCDFE6;
    border-bottom: 1px solid #DCDFE6;
    content: '';
  }
  .delBTN{
    height: 30px;
    background: #EEF7FF;
    border-radius: 50% !important;
    color: #1890FF;
    border: none;
    margin-top: 5px;
  }

</style>
